#include <assert.h>
#include <string.h>

#include "list_p.h"
#include "vmalloc.h"

#include "vtl_list.h"

struct list_node
{
    void *data;
    struct list_head head;
};

struct __list
{
    size_t size; //个数
    size_t typesize;// 数据类型大小
    vListOps *list_ops;
    struct list_head head;
};

//创建和销毁
vList *vListNew(size_t typesize,vListOps *ops)
{
    struct __list *a_this = NULL;

    if(typesize <= 0)
        return NULL;

    a_this = (struct __list *)vCalloc(1,sizeof(struct __list));
    assert(a_this);

    INIT_LIST_HEAD(&a_this->head);
    a_this->size = 0;
    a_this->typesize = typesize;
    a_this->list_ops = ops;

    return (vList)a_this;
}

void vListDelete(vList ls)
{
    struct __list *a_this = (struct __list *)ls;
    assert(a_this);
    /* del all node */
    struct list_node *node,*n;
    list_for_each_entry_safe(node,n,&a_this->head,head,struct list_node)
    {
        list_del(&node->head);/* del node from list */
        if(a_this->list_ops->vListFree)
        {
            a_this->list_ops->vListFree(node->data); /* del data */
        }
        free(node);
    }
    a_this->size = 0;
    vFree(a_this);
}


bool vListEmpty(vList ls)
{
    struct __list *a_this = (struct __list *)ls;
    assert(a_this);
    return (list_empty(&a_this->head) == 1);
}
size_t vListList(vList ls)
{
    struct __list *a_this = (struct __list *)ls;
    assert(a_this);
    return a_this->size;
}

vListIterator vListPushFront(vList ls,void *data)
{
    struct __list *a_this = (struct __list *)ls;
    return vListInsert(ls,(vList)(&a_this->head),data);
}
vListIterator vListPushBack(vList ls,void *data)
{
    struct __list *a_this = (struct __list *)ls;
    return vListInsert(ls,(vList)(&a_this->head.prev),data);
}
vListIterator vListInsert(vList ls,vListIterator pos1,void *data)
{
    struct __list *a_this = (struct __list *)ls;
    struct list_head *pos = (struct list_head *)pos1;

    if(!a_this || !pos)
        return NULL;

    struct list_node *node = (struct list_node *)vCalloc(1,sizeof(struct list_node));
    if(!node)
        return NULL;

    if(a_this->list_ops && a_this->list_ops->vListAlloc)
    {

        node->data = a_this->list_ops->vListAlloc(data);
        assert(node->data);
        memcpy(node->data,data,a_this->typesize);
    }
    else
    {
        node->data = data;
    }

    list_add(&node->head,pos);
    a_this->size++;

    return (vListIterator)&node->head;
}

void vListFreeIterator(vListIterator it)
{
    vFree(it);
}

void *vListPopFront(vList ls)
{
    struct __list *a_this = (struct __list *)ls;
    assert(a_this);
    if(list_empty(&a_this->head))
        return NULL;

    struct list_node *node = list_first_entry(&a_this->head,struct list_node,head);
    return node->data;
}
void *vListPopBack(vList ls)
{
    struct __list *a_this = (struct __list *)ls;
    assert(a_this);
    if(list_empty(&a_this->head))
        return NULL;

    struct list_node *node = list_last_entry(&a_this->head,struct list_node,head);
    return node->data;
}

vListIterator vListInsertBefore(vList ls,vListIterator pos1,void *data)
{
    struct __list *a_this = (struct __list *)ls;
    struct list_head *pos = (struct list_head *)pos1;

    struct list_node *node = (struct list_node *)vCalloc(1,sizeof(struct list_node));
    if(!node)
        return NULL;

    if(a_this->list_ops && a_this->list_ops->vListAlloc)
    {

        node->data = a_this->list_ops->vListAlloc(data);
        assert(node->data);
        memcpy(node->data,data,a_this->typesize);
    }
    else
    {
        node->data = data;
    }

    list_add_tail(&node->head,pos);
    a_this->size++;

    return (vListIterator)&node->head;
}

vListIterator vListErase(vList ls,vListIterator pos1)
{
    struct __list *a_this = (struct __list *)ls;
    struct list_head *it = (struct list_head *)pos1;

    struct list_head *next = it->next;
    list_del(it);
    a_this->size--;

    struct list_node *node = list_entry(it,struct list_node,head);
    if(a_this->list_ops->vListFree)
    {
        a_this->list_ops->vListFree(node->data);
    }
    free(node);

    return (vListIterator)next;
}

vListIterator vListEraseFront(vList ls)
{
    struct __list *a_this = (struct __list *)ls;
    assert(a_this);
    if(list_empty(&a_this->head))
        return NULL;

    return vListErase(a_this,a_this->head.next);
}
vListIterator vListEraseBack(vList ls)
{
    struct __list *a_this = (struct __list *)ls;
    assert(a_this);
   if(list_empty(&a_this->head))
       return NULL;

   return vListErase(a_this,a_this->head.prev);
}

vListIterator vListFind(vList ls,void *data)
{
    UNUSED(ls);
    UNUSED(data);
}

void vListReverse(vList ls)
{
    UNUSED(ls);
}

void vListClear(vList ls)
{
    UNUSED(ls);
}

vList vListMerge(vList ls1,vList ls2)
{
    UNUSED(ls1);
    UNUSED(ls2);
}
